////////////////////////////////////////////////////////////////////////////////

#include "server_network.h"

////////////////////////////////////////////////////////////////////////////////

#include <boost/bind.hpp>
#include <ctime>
#include "server.h"

////////////////////////////////////////////////////////////////////////////////


ServerNetwork::ServerNetwork( int _port, boost::asio::io_service& _io_service )
: m_io_service(_io_service),
  m_Acceptor(m_io_service, tcp::endpoint(tcp::v4(), _port) )
{
}


////////////////////////////////////////////////////////////////////////////////


ServerNetwork::~ServerNetwork()
{
}


////////////////////////////////////////////////////////////////////////////////


void ServerNetwork::Start( Server* _server )
{
    // Server interface
    m_Server = _server;

    // Start accepting new connections
    StartAccept();
}

////////////////////////////////////////////////////////////////////////////////


void ServerNetwork::StartAccept()
{
    // Create new session
    ServerSession* newSession = new ServerSession(m_io_service, m_Server);
    
    // Accept connection
    m_Acceptor.async_accept( newSession->GetSocket(),
                             boost::bind( &ServerNetwork::HandleAccept,
                                          this,
                                          newSession) );
}


////////////////////////////////////////////////////////////////////////////////


void ServerNetwork::HandleAccept( ServerSession* _newSession )
{
    static char clientID = 0;

    // Send to client its ID
    size_t bytesSent = _newSession->GetSocket().send(
        boost::asio::buffer( &clientID, sizeof(char) ) );
    assert( bytesSent == sizeof(char) );

    // Prepare for next client
    ++clientID;

    // Send server time to client
    clock_t serverTime = clock();
    bytesSent = _newSession->GetSocket().send(
        boost::asio::buffer( &serverTime, sizeof(clock_t) ) );
    assert( bytesSent == sizeof(clock_t) );

    // Add session
    m_Sessions.push_back(_newSession);

    // Start receiving
    _newSession->Receive();

    // Accept new connection
    StartAccept();
}


////////////////////////////////////////////////////////////////////////////////


void ServerNetwork::Send( const ServerPacket& _packet )
{
    // Send to all sessions
    for (ServerSessions::iterator it = m_Sessions.begin(); it != m_Sessions.end(); )
    {
        ServerSession* session = *it;

        if ( session->IsOK() )
        {
            session->Send(_packet);
            ++it;
        }
        else
        {
            it = m_Sessions.erase(it);
            delete session;
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
